home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Medal Software 2
/
Gold Medal Software Volume 2 (Gold Medal) (1994).iso
/
prog
/
asm_n_z.arj
/
STOCHAIN.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-10-24
|
28KB
|
807 lines
PAGE 60,132
;program to chain and form DOS storage blocks
; Usage is: STOCHAIN
sb SEGMENT AT 0 ;map of storage block header paragraph
sbkind DB ' ' ;Type of storage block: M or Z
sbpsp DW 0 ;PSP segment address
sblength DW 0 ;SB length in paragraphs
sbfill DB 11 DUP(0) ;filler
ORG sbkind
pspretint DW ? ;int 20
pspmemsize DW ? ;size of memory in paragraphs
pspresv DB ?
ORG 5h
pspcalldosfunct DB ? ;long call to dos function dispatcher
pspdosfunct DD ? ;IP:CS of dos function dispatcher
ORG 0Ah
pspdosterminate DD ? ;IP:CS of:dos terminate
ORG 0Eh
pspdosctrlbreak DD ? ; ctrl break address
ORG 12h
pspdoscrtclerr DD ? ; critical error handler
ORG 18h
pspdosdefhandle DD 20 dup(?) ; DOS 2.0 - 20 file handles
; DOS 3.0 - default file handles
ORG 2Ch
pspenv DW ? ;segment address of environment
ORG 32h
psphandlecount DW ? ;number of handles in table (DOS 3.0)
ORG 34h
psphandles DW ? ;offset of handle table in CS (DOS 3.0)
ORG 50h
pspdosfunction DW ? ;invoke dos function dispatcher
ORG 5Ch
pspfcb1 DB ? ;first fcb
ORG 6Ch
pspfcb2 DB ? ;second fcb
ORG 80h
pspparm DB ? ;unformatted paramter area
ORG 0FFh
pspend EQU $
sb ENDS
code_seg SEGMENT
ASSUME CS:code_seg,DS:code_seg,ES:sb
cr equ 13
lf equ 10
myretint DW ? ;int 20
ORG 50h
mydosfunction DW ? ;invoke dos function dispatcher
ORG 100h
code PROC far
jmp program
db 'Copyright 1986 by Arnold B. Krueger GPW MI, 48236'
typestring proc near
push ax
mov ax,0900h
int 21h
pop ax
ret
typestring endp
getfirstsb PROC near ;get first storage block, ES will point to it
PUSH AX
PUSH BX
MOV AX,5200h
INT 21h ;ES:BX points to memory block anchor+2
DEC BX
DEC BX
MOV ES,ES:[BX] ;get first memory block address into ES
POP BX
POP AX
RET
getfirstsb ENDP
getnextsb PROC near
PUSH AX
MOV AX,ES ;get current paragraph
ADD AX,[SBLENGTH] ;add in number of paragraphs
INC AX ;add 1 for header
MOV ES,AX ;set new extra segment address
POP AX
RET
getnextsb ENDP
hexformat equ $
hexaddrhi dw 0
hexaddrlo dw 0
db ':0 '
hexdata dw 18 dup(0)
hexdataend db '*$'
hexend db '*'
crlf db cr,lf,'$'
indent db 5 dup(' '),'$'
asciizl proc near ;string, length in CX
; at ES:DI searched for 0h
;new length in CX
push ax
xor al,al ;search for zero
call charstrl
pop ax
ret
asciizl endp
charstrl proc near ;string length in CX
;string at ES:DI searched for char in AL
;new length in CX
push ax
push di ;save register
push cx ;save cx
repnz scasb ;do search
jcxz charsterror ;if cx exhausted, may be error
charsthit:
mov ax,cx ;save count remaining
pop cx ;restore old cx
sub cx,ax ;subtract length
dec cx ;knock off 1 for failed test
jcxz charstnull ;if zero length, error
clc ;clear carry flag
jmp charstexit ;and exit
charsterror:
dec di ;back up
cmp al,es:[di] ;check last byte
je charsthit ;if what we want, use it
pop cx ;pull off saved cx
charstnull:
stc ;set error flag
charstexit:
pop di ;restore registers
pop ax
ret
charstrl endp
hextocharlist db '0123456789ABCDEF'
hextochar PROC near ;AL (hex) -> AX (characters)
PUSH SI
PUSH DX
PUSH CX
PUSH AX
XOR DX,DX
AND AX,0fh ;isolate low nibble
ADD AX,offset hextocharlist
MOV SI,AX ;get address of character
MOV DH,[SI] ;get character
POP AX
AND AX,0f0h ;isolate high nibble
MOV CL,4
SHR AX,CL
ADD AX,offset hextocharlist
MOV SI,AX ;get address of character
OR DL,[SI] ;get character
MOV AX,DX
POP CX
POP DX
POP SI
RET
hextochar ENDP
Hexline proc near ;type paragraph at ES: in hex
push si
push cx
push ax
push es
pop ax
call hextochar ;get low byte
mov hexaddrlo,ax
push es
pop ax
mov al,ah ;get high byte
call hextochar
mov hexaddrhi,ax
xor si,si
mov di,offset hexdata
mov cx,4
hexparaloop: ;loop 4 times per paragraph
push cx
mov cx,4
hexwordloop: ;loop 4 times per doubleword
mov al,es:[si]
call hextochar
mov ds:[di],ax
inc di
inc di
inc si
loop hexwordloop
mov byte ptr ds:[di],' '
inc di
pop cx
loop hexparaloop
pop ax
pop cx
pop si
ret
hexline endp
chartype proc near ;type CX bytes at ES:DI if typable
stc ;possible error
jcxz chartypeexit ;if nothing to type, exit
push ax
push cx
push dx
push di
chartypeloop:
mov dl,es:[di]
cmp dl,126 ;printer/console
; cmp dl,254 ;console only
ja chartypefix
cmp dl,31
ja chartypeit
jmp chartypefix ;printer/console
cmp dl,26 ;console only
ja chartypefix
cmp dl,13
ja chartypeit
cmp dl,6
ja chartypefix
cmp dl,0
ja chartypeit
chartypefix: mov dl,'.'
chartypeit: mov ax,0200h
int 21h
inc di
loop chartypeloop
clc ;no error
pop di
pop dx
pop cx
pop ax
chartypeexit:
ret
chartype endp
hextype proc near ;proc to hex type data at ES:0
push ax
push cx
push dx
push di
call hexline
mov dx,offset hexformat
call typestring
mov cx,16
xor di,di
call chartype
mov dx,offset hexend
call typestring
pop di
pop dx
pop cx
pop ax
ret
hextype endp
sbbackup proc near ;decrement es by one
push ax ;save work register
push es ;back up
pop ax
dec ax ;and address storage block header
push ax
pop es
pop ax ;restore work register
ret
sbbackup endp
sbinc proc near ;increment es by one
push ax ;save work register
push es
pop ax
inc ax ;and address storage block contents
push ax
pop es
pop ax ;restore work register
ret
sbinc endp
progenvmsg db 'Program environment block questionable',cr,lf,'$'
progenvend proc near ;find end of environment in ES:0
push ax ;update DI, remaining length in CX
push bx
push dx
push es
call sbbackup ;backup over storage block header
mov bx,[sblength] ;get length of storage block
pop es ;restore ES
push es ;restore stack
mov cl,4 ;multiply BX by 16
shl bx,cl
mov cx,bx ;number of words in environment
xor di,di
xor ax,ax
cld ;scan forward
progenvscan: ;loop through environment
scasw ;compare a word at ES:DI
jz progenvfinis ;if equal, exit loop
dec di ;go forward only 1 byte
loop progenvscan ;and scan on
progenvfinis:
jcxz progenvshort ;if we ran out, error
dec di ;back up a byte
mov ax,1 ;now look for '0001'h
progenvedit:
scasw
jz progenvprog ;got one? then go on
dec di ;back up a byte
loop progenvedit
jcxz progenvshort
progenvprog:
clc ;clear carry flag
;ES:DI points to program name
jmp progenvexit
progenvshort:
mov dx,offset progenvmsg
progenverror:
call typestring
stc ;set carry flag
progenvexit:
pop es ;restore registers
pop dx
pop bx
pop ax
ret
progenvend endp
progtypedos2msg db 'Program name not available in DOS 2.0',cr,lf,'$'
progtypeformat db 'Program name:$'
progtypenameover db ' program name overlaid',cr,lf,'$'
progtypename proc near ;es points to environment
push dx
push bx
push ax
mov ah,30h ;get release number
int 21h
cmp al,02h ;above dos 2.0?
jna progtypedos2
call progenvend ;find environment end in ES:DI, length: CX
jc progtypenoname ;if not found, just exit
mov dx,offset progtypeformat ;type out header
call typestring
mov dx,offset indent
call typestring
call asciizl ;length of asciiz string at ES:DI to CX
jc progtypenoname
cmp cx,3 ;minimum length of individual item
jb progtypenoname
cmp cx,255 ;maximum length of individual item
ja progtypenoname
call chartype
mov dx,offset crlf
call typestring
clc
jmp progtypenameexit
progtypedos2:
mov dx,offset progtypedos2msg
call typestring
stc
jmp progtypenameexit
progtypenoname:
mov dx,offset progtypenameover
call typestring
stc
progtypenameexit:
pop ax
pop bx
pop dx
ret
progtypename endp
progtypeenvformat db 'Program environment string at: '
progtypeenvaddhi dw 0
progtypeenvaddlo dw 0
db ':0',cr,lf,'$'
progtypeenvbadmsg db 'Program environment string overlaid',cr,lf,'$'
progtypeenv proc near ;type out environment strings at ES:0
push ax
push cx
push di
push dx
push es
pop ax
call hextochar
mov progtypeenvaddlo,ax
push es
pop ax
mov al,ah
call hextochar
mov progtypeenvaddhi,ax
mov dx,offset progtypeenvformat
call typestring
xor di,di ;type out environment strings
cmp byte ptr es:[di],0 ;common type of trashing of environment
je progtypeenvbad
xor ax,ax ;make ax zero for end of environment search
progtypeenvloop:
mov dx,offset indent ;print out some blanks
call typestring
mov cx,128 ;search a ways
call asciizl ;get length of asciiz string
jc progtypeenvbad ;if error, skip out
cmp cx,3 ;minimum length of individual item
jb progtypeenvbad
cmp cx,255 ;maximum length of individual item
ja progtypeenvbad
call chartype ;type it out
jc progtypeenvbad ;if error, skip out
add di,cx ;add in its length
mov dx,offset crlf ;print out a cr, lf
call typestring
scasw ;look at next word
jz progtypeenvend ;if zero, end of environment
dec di ;otherwise back up a byte
jmp progtypeenvloop ;and look again
progtypeenvbad:
mov dx,offset progtypeenvbadmsg ;complain about environment
call typestring
stc ;return error
progtypeenvend:
pop dx
pop di
pop cx
pop ax
ret
progtypeenv endp
progtypeparmformat db 'Program calling parameters: $'
progtypeparmnone db '(none)',cr,lf,'$'
progtypeparm proc near ;type out parm area of PSP at ES:0
push ax
push cx
push di
push dx
mov dx,offset progtypeparmformat
call typestring ;print out heading
mov di,offset pspparm ;ES:DI to parameter list
mov al,es:[di] ;get parm length
cmp al,127 ;if impossible, skip out
ja progtypenoparm
inc di ;now look at actual data
mov cx,255
mov al,cr ;look for carriage return
call charstrl ;get actual length of parms
jc progtypenoparm ;error detected, forget it
jcxz progtypenoparm ;if null parm, skip out
cmp cx,127 ;if impossible, skip out
ja progtypenoparm
call chartype ;if good, type out
mov dx,offset crlf
call typestring
clc
jmp progtypeparmexit
progtypenoparm: ;no parms
mov dx,offset progtypeparmnone
call typestring
stc
progtypeparmexit:
pop dx
pop di
pop cx
pop ax
ret
progtypeparm endp
progtypenoenvmsg db 'Program has no environment block',cr,lf,'$'
progtypefirstprog db 0
yes equ 1
progtypedospsp dw 0 ;segment address of first command.com resident part
progtype proc near ;format program storage block at ES:0
push ax
push bx
push cx
push dx
push es
clc
call sbinc ;program follows SB header
push es ;save ES in BX
pop bx
mov ax,[mydosfunction]
cmp ax,[pspdosfunction] ;check PSP validity
jne progtypenoenv ;around byte 0h
mov ax,[myretint]
cmp ax,[pspretint] ;check PSP validity
jne progtypenoenv ;if invalid, skip looking for env
cmp progtypefirstprog,yes ;is this the first program
je progtypenotdos
mov progtypefirstprog,yes
push ES
pop AX
mov progtypedospsp,AX ;save first resident command.com
progtypenotdos:
mov ax,[pspenv] ;get environment of program
cmp ax,0
je progtypenoenv ;if no environment, say so
push ax
pop es ;ES points to environment
call progtypename ;format program name from environment
call progtypeenv ;format environment strings
push bx
pop es ;back to looking at program PSP
call progtypeparm ;format program parm area
jmp progtypeend
progtypenoenv: ;no environment (!!)
mov dx,offset progtypenoenvmsg
call typestring
stc
progtypeend:
pop es
pop dx
pop cx
pop bx
pop ax
ret
progtype endp
sbformat equ $
db 'Storage block at:'
sbaddrhi dw 0
sbaddrlo dw 0
db ':0 PSP of owner at:'
sbpsphi dw 0
sbpsplo dw 0
db ':0 Block length:'
sblengthhi dw 0
sblengthlo dw 0
sbcrlf db cr,lf,'$'
sbglobalmsg db 'Storage block is the global environment',cr,lf,'$'
sbnotprogmsg db 'Storage block is not a program',cr,lf,'$'
sbsystemmsg db 'Storage block is system owned',cr,lf,'$'
sbfreemsg db 'Storage block is free',cr,lf,'$'
sbconfigmsg db 'Storage block belongs to CONFIG.SYS',cr,lf,'$'
sbprogmsg db 'Storage block is a program',cr,lf,'$'
sbproghead db 'Program PSP contents:',cr,lf,'$'
sbdatahead db 'Storage block contents: (first 128 bytes)',cr,lf,'$'
sbhead db 'Storage header contents:',cr,lf,'$'
sbtype proc near ;format out block
push ax ;save registers
push cx
push dx
push es ;format out block header
pop ax ;format block address
call hextochar ;get low byte
mov sbaddrlo,ax
push es
pop ax
mov al,ah ;get high byte
call hextochar
mov sbaddrhi,ax
mov al,byte ptr sblength ;format block length
call hextochar
mov sblengthlo,ax
mov al,byte ptr sblength+1
call hextochar
mov sblengthhi,ax
mov al,byte ptr sbpsp ;format block psp pointer
call hextochar
mov sbpsplo,ax
mov al,byte ptr sbpsp+1
call hextochar
mov sbpsphi,ax
mov dx,offset sbformat ;type out formatted data
call typestring
mov ax,[sbpsp] ;get PSP of owner
cmp ax,0 ;if zero, it is free
je sbfree
cmp ax,8 ;if PSP of owner is at 8
je sbconfig ;block owned by config.sys
cmp ax,progtypedospsp ;is owner command.com
je sbglobalenv
;get address of SB
push es
pop ax
cmp ax,[sbpsp] ;compare to address of owner
ja sbsystem ;if owner below SB, system-owned
add ax,[sblength] ;add in length
cmp ax,[sbpsp] ;compare to owner's PSP
JB sbnotprogram ;if end below owner PSP, no program
cmp [sblength],10 ;is block long enough to have a psp?
jbe sbnotprogram ;if not, no program
mov dx,offset sbprogmsg ;type out formatted data
call typestring
call progtype
mov dx,offset sbproghead ;type out formatted data
jmp sbjoin
sbglobalenv:
mov dx,offset sbglobalmsg ;say it is global envrionment
call typestring
push es
call sbinc
call progtypeenv ;type out environment
pop es
mov dx,offset sbdatahead ;type heading for hex data
jmp sbjoin
sbsystem:
mov dx,offset sbsystemmsg ;say it belongs to the system
call typestring
mov dx,offset sbdatahead ;type heading for hex data
jmp sbjoin
sbnotprogram:
mov dx,offset sbnotprogmsg ;say it is not a program
call typestring
mov dx,offset sbdatahead ;type heading for hex data
jmp sbjoin
sbfree:
mov dx,offset sbfreemsg ;say it is free storage
call typestring
mov dx,offset sbdatahead ;type heading for hex data
jmp sbjoin
sbconfig:
mov dx,offset sbconfigmsg ;say it belongs to config.sys
call typestring
mov dx,offset sbdatahead ;type heading for hex data
sbjoin:
call typestring
sbdisplay:
mov cx,[sblength] ;format first 16 or less paragraphs
cmp cx,16
jb sbsmall
mov cx,16
sbsmall:
push es ;save ES:
sbloop:
mov ax,es
inc ax
mov es,ax
call hextype
loop sbloop
sbexit:
pop es ;restore registers
pop dx
pop cx
pop ax
ret
sbtype endp
badblok_msg db 'Bad storage block encountered',cr,lf,'$'
lastblok_msg db 'End of storage block chain reached',cr,lf,'$'
baddos_msg db 'Must be running under DOS 2.0 or above',cr,lf,'$'
program: ;this is the actual main line program
mov ah,30h ;get release number
int 21h
cmp al,01h ;above dos 1.x?
jna baddos
cld ;clear direction flag
call getfirstsb ;ES points to first SB
sblook: ;loop all storage blocks
MOV al,sbkind ;get storage block type byte
cmp al,04dh ;ordinary storage block
je gotblok
cmp al,05ah
je lastblok ;last storage block
jmp badblok
gotblok:
mov dx,offset sbhead ;type out formatted data
call typestring
call hextype
call sbtype
call getnextsb
mov dx,offset crlf
call typestring
jmp sblook
lastblok:
call hextype
call sbtype
mov dx,offset lastblok_msg
jmp sendmsg
baddos:
mov dx,offset baddos_msg
jmp sendmsg
badblok:
call hextype
mov dx,offset badblok_msg
sendmsg:
call typestring
INT 20h
code ENDP
code_seg ENDS
END code
]├ Uï∞ï ∩ ≤3▓√C è ëùë>wë6y╬ë{úâ3╔█u1╟ü